<template>
  <h1>reactive</h1>
  <!-- reactive -->
  <h3>reactive</h3>
  <div class="main-content">
    <h3>修改个人信息</h3>
    <div v-for="(value, key) in infos" :key="key">
      <div v-if="key === 'other'"></div>
      <div v-else class="info-item-text">{{ keys[key] }}: {{ value }}</div>
      <template v-if="key !== 'other'">
        <el-input
          v-model="infos[key]"
          style="width: 240px; margin-right: 10px"
          maxlength="5"
          show-word-limit
          placeholder="Please input"
          :class="{ sucessBorder: isEditType === key }"
          @blur="blurHandle"
        />
        <span> {{ isEditType === key ? "修改中" : "" }}</span>
      </template>
      <div v-else @click="infos[key].hobby = '听歌'">
        {{ infos[key].hobby }}
      </div>
      <!-- 用typeof value === 'string'作判断，ts会自动判断该结果会有多种情况类型出现，很难判断 -->
      <!-- <el-input
        v-if="typeof value !== 'object'"
        v-model="infos[key]"
        style="width: 240px"
        maxlength="5"
        show-word-limit
        placeholder="Please input"
      /> -->
    </div>
    <el-button @click="modifyInfo" class="modify-btn" type="success"
      >替换全部信息</el-button
    >
  </div>
</template>

<script setup lang="ts">
import { onUpdated, reactive, ref, watch, watchEffect } from "vue";
const keys = {
  name: "姓名",
  age: "年龄",
  sex: "性别",
  other: "其他",
};
interface Person {
  name: string;
  age: string;
  sex: string;
  other: {
    hobby: string;
  };
}

let infos: Person = reactive({
  name: "yanx",
  age: "18",
  sex: "女",
  other: {
    hobby: "音乐",
  },
});
function modifyInfo() {
  //   infos = { name: "hhhh", age: "19", sex: "你猜" };
  //   infos = Object.assign({}, infos, { name: "hhhh", age: "19", sex: "你猜" });
  //   infos = { ...infos, name: "yyyyy", age: "19", sex: "你猜" };
  const data = { name: "", age: "", sex: "", other: { hobby: "" } };

  // 这种方法叫修改（因为修改的是对象里的值），而不是替换（替换应该是替换整个地址值）
  infos = Object.assign(infos, data);
  //   infos.value = data;

  console.log("infos", infos);
}

// 这个触发新值和旧值返回的都是同一个对象结果，这里监听的是对象的地址值，无法窥看对象内部变化
// watch(infos, (newVal, oldVal) => {
//   console.log("触发了", newVal, oldVal);
// });

// 参数{ immediate: true, deep: true }
// 监视【reactive】定义的【对象类型】数据，默认是开启深度监视的，并且这个监视是不可以关闭的
// watch(
//   infos,
//   (newVal, oldVal) => {
//     console.log("触发了", newVal, oldVal);
//   },
//   { immediate: true, deep: true }
// );

// 监听对象内部多个属性变化
let isEditType: any = ref(null);
watch(
  [() => infos.name, () => infos.age, () => infos.sex, () => infos.other],
  (newVal, oldVal) => {
    isEditType = getDiffKey(infos, newVal, oldVal);
    console.log(isEditType);
    console.log(newVal, oldVal);
  },
  { deep: true }
);

watchEffect(() => {
  // console.log("hobby:", infos.other.hobby);
});

function getDiffKey(obj: Object, arr1: Array<any>, arr2: Array<any>) {
  const keys = [];
  for (let key in obj) {
    keys.push(key);
  }
  const idx = arr1.findIndex((item, idx) => item !== arr2[idx]);
  return keys[idx];
}
function blurHandle() {
  isEditType = null;
  // console.log(isEditType);
}

// onUpdated(() => {
//   console.log("触发了");
// });
</script>

<style scoped>
h3 {
  color: #444;
  padding: 10px 0;
}
.main-content {
  margin: 20px 0;
  padding: 10px;
  border: 1px solid #dddfe6;
  border-radius: 5px;
}
.info-item-text {
  display: inline-block;
  width: 150px;
  margin: 10px 0;
}
.modify-btn {
  margin: 20px 0;
}
.sucessBorder {
  border: 1px solid green;
  border-radius: 5px;
}
</style>
